package com.ygqh.baby.service.task.impl;

import com.ygqh.baby.ao.Message;
import com.ygqh.baby.ao.TaskMethod;
import com.ygqh.baby.ao.YgQuartzJob;
import com.ygqh.baby.model.ProductBookRecordModel;
import com.ygqh.baby.po.YgPrepayBookRecord;
import com.ygqh.baby.po.YgProductBook;
import com.ygqh.baby.po.YgUser;
import com.ygqh.baby.service.*;
import com.ygqh.baby.service.impl.BaseWxMpMessageService;
import com.ygqh.baby.service.task.YgProductBookTaskService;
import com.ygqh.baby.utils.DateConvertUtils;
import com.ygqh.baby.utils.ExceptionUtil;
import com.ygqh.baby.utils.YgStringUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

/**
 * @Auther: sunshuo
 * @Date: 2018/8/2 10:55
 * @Description:
 */
@Service
public class YgProductBookTaskServiceImpl implements YgProductBookTaskService {

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private YgTaskTimeService ygTaskTimeService;
    @Autowired
    private YgPrepayBookRecordService ygPrepayBookRecordService;
    @Autowired
    private YgProductBookService ygProductBookService;
    @Autowired
    private ScheduleJobService scheduleJobService;
    @Autowired
    private BaseWxMpMessageService baseWxMpMessageService;
    @Autowired
    private YgUserService ygUserService;
    @Value("${promotion.link}")
    protected String promotionLink;
    @Autowired
    private SmsService smsService;
    @Autowired
    private WxMpAuthorityService wxMpAuthorityService;

    /**
     * 取消超时未支付定金的活动订单；
     */
    @Override
    public void cancelRecod() {
        Date runTime = new Date();
        try {
            List<ProductBookRecordModel> recordList = ygPrepayBookRecordService.findForCancel(DateConvertUtils.addDay(runTime, -1));
            if (!CollectionUtils.isEmpty(recordList)) {
                logger.warn("活动订单超时未支付记录数：" + recordList.size());
                for (ProductBookRecordModel record : recordList) {
                    ygPrepayBookRecordService.cancelRecord(record.getRecordCode());
                }
            }
            ygTaskTimeService.saveOrUpdate(TaskMethod.CancelBookRecord.name(), runTime, "【活动订单超时未支付取消任务】执行成功");
        } catch (Exception e) {
            e.printStackTrace();
            ygTaskTimeService.saveOrUpdate(TaskMethod.CancelBookRecord.name(), runTime, "【活动订单超时未支付取消任务】执行失败。error=" + ExceptionUtil.getExceptionMsg(e));
        }
    }

    @Override
    public void addPaidTailJob(YgProductBook ygProductBook) {
        new Thread(() -> {
            Date now = DateConvertUtils.getDateStart(new Date());
            if (now.compareTo(DateConvertUtils.getDateStart(ygProductBook.getBookEndTime())) <= 0) { // 支付定金结束后
                Date runTime = DateConvertUtils.addDay(DateConvertUtils.getDateStart(ygProductBook.getBookEndTime()), 1);
                this.addProductBook(ygProductBook.getId(), TaskType.BookEnd, runTime, "支付定金结束，取消所有未支付定金的记录");
            }
            if (now.compareTo(DateConvertUtils.getDateStart(ygProductBook.getTailMoneyStartTime())) < 0) { // 支付尾款开始前
                Date runTime = DateConvertUtils.getDateStart(ygProductBook.getTailMoneyStartTime());
                this.addProductBook(ygProductBook.getId(), TaskType.TailStart, runTime, "支付尾款开始提醒");
            } else if (now.compareTo(DateConvertUtils.getDateStart(ygProductBook.getTailMoneyEndTime())) <= 0) { // 支付尾款结束后
                Date runTime = DateConvertUtils.addDay(DateConvertUtils.getDateStart(ygProductBook.getTailMoneyEndTime()), 1);
                this.addProductBook(ygProductBook.getId(), TaskType.TailEnd, runTime, "支付尾款结束定金不退，赠送优惠券");
            }
        }).start();
    }

    @Override
    public void tailPricePaidRemind(Long bookId, TaskType taskType) {
        YgProductBook productBook = ygProductBookService.findById(bookId);
        switch (taskType) {
            case BookEnd:
                this.cancelRecodByBookId(productBook.getId(), YgPrepayBookRecord.RecordStatus.WaitingPayDepost);
                break;
            case TailStart: // 支付尾款开始提醒
                this.sendTailRemindBookId(productBook.getId());
                Date runTime = DateConvertUtils.addDay(DateConvertUtils.getDateStart(productBook.getTailMoneyEndTime()), 1);
                this.addProductBook(productBook.getId(), TaskType.TailEnd, runTime, "支付尾款结束定金不退，赠送优惠券");
                break;
            case TailEnd:// 支付尾款结束定金不退，赠送优惠券
                /*this.refundRecordByBookId(productBook.getId());*/
                // 有关记录单取消并赠送优惠券
                this.cancelRecodByBookId(productBook.getId(), YgPrepayBookRecord.RecordStatus.WaitingPayFinal);
                break;
            default:
                break;
        }
    }

    private void cancelRecodByBookId(Long bookId, YgPrepayBookRecord.RecordStatus recordStatus) {
        List<ProductBookRecordModel> modelList = ygPrepayBookRecordService.findByBookId(bookId, recordStatus);
        if (CollectionUtils.isEmpty(modelList)) {
            return;
        }
        if (YgPrepayBookRecord.RecordStatus.WaitingPayDepost.equals(recordStatus)) {
            logger.info("定金活动(id=" + bookId + ")定金支付过期记录数：" + modelList.size());
            for (ProductBookRecordModel model : modelList) {
                ygPrepayBookRecordService.cancelRecord(model.getRecordCode());
            }
        } else if (YgPrepayBookRecord.RecordStatus.WaitingPayFinal.equals(recordStatus)) {
            logger.info("定金活动(id=" + bookId + ")尾款支付过期记录数：" + modelList.size());
            Map<Long, List<ProductBookRecordModel>> modelMap = groupRecordModelByOrderId(modelList);
            for (Map.Entry<Long, List<ProductBookRecordModel>> entry :
                    modelMap.entrySet()) {
                ygPrepayBookRecordService.cancelRecord(entry.getKey(), entry.getValue());
            }
        }
    }

    /**
     * 尾款支付开始提醒
     *
     * @param bookId 活动id
     */
    private void sendTailRemindBookId(Long bookId) {
        List<ProductBookRecordModel> modelList = ygPrepayBookRecordService.findByBookId(bookId, YgPrepayBookRecord.RecordStatus.WaitingPayFinal);
        if (CollectionUtils.isEmpty(modelList)) {
            return;
        }
        logger.info("定金活动(id=" + bookId + ")定金支付记录数：" + modelList.size());
        Set<Long> userIdSet = modelList.stream().map(ProductBookRecordModel::getUserId).collect(Collectors.toSet());
        List<YgUser> userList = ygUserService.findOpenIds(new ArrayList<>(userIdSet));
        logger.info("定金活动(id=" + bookId + ")尾款支付通知用户数：" + userList.size());
        Map<Long, List<YgUser>> userMap = userList.stream().collect(Collectors.groupingBy(YgUser::getId));
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10);
        String url = promotionLink + "/user/activitylist.html";
        String smsContent = "您的定金活动产品可以付尾款了，尽快支付吧 ";
        for (ProductBookRecordModel model : modelList) {
            fixedThreadPool.execute(() -> {
                if (!userMap.containsKey(model.getUserId())) {
                    return;
                }
                YgUser user = userMap.get(model.getUserId()).get(0);
				/*String title = "您预定的 " + model.getProductName() + " 可以支付尾款了，请于"
						+ DateConvertUtils.format(DateConvertUtils.addDay(model.getTailMoneyEndTime(), 1)) + "前支付完成哦";
				baseWxMpMessageService.sendTemplateMessage(WxMessageType.TailMoneyPaid, title, "尾款支付成功后我们会按付款先后顺序尽快为您安排发货。",
						user.getOpenId(), url, model.getRecordCode().toString(), DateConvertUtils.formatDateTime(model.getCreateTime()),
						model.getBookPrice().setScale(0, BigDecimal.ROUND_HALF_DOWN).toString(),
						model.getTailPrice().setScale(0, BigDecimal.ROUND_HALF_DOWN).toString());*/
                if (YgStringUtils.isChinaPhoneLegal(user.getUserName())) {
                    smsService.sendSms(user.getUserName(), smsContent);
                }

            });
        }
        fixedThreadPool.shutdown();
    }

    /*
     * 尾款支付结束，退定金
     *
     * @param bookId
     */
	/*private void refundRecordByBookId(Long bookId) {
		List<ProductBookRecordModel> modelList = ygPrepayBookRecordService.findByBookId(bookId, YgPrepayBookRecord.RecordStatus.WaitingPayFinal);
		if (CollectionUtils.isEmpty(modelList)) {
			return;
		}
		logger.error("定金活动(id=" + bookId + ")定金支付过期记录数：" + modelList.size());
		Map<Long, List<ProductBookRecordModel>> modelMap = groupRecordModelByOrderId(modelList);
		for (Map.Entry<Long, List<ProductBookRecordModel>> entry :
			 modelMap.entrySet()) {
			ygPrepayBookRecordService.refundRecord(entry.getKey(), entry.getValue());
		}
	}*/

    /**
     * 以订单号分组活动记录
     *
     * @param modelList 活动记录集
     * @return Map
     */
    private Map<Long, List<ProductBookRecordModel>> groupRecordModelByOrderId(List<ProductBookRecordModel> modelList) {
        Map<Long, List<ProductBookRecordModel>> modelMap = new HashMap<>();
        for (ProductBookRecordModel model :
                modelList) {
            Long orderId = model.getOrderId() == null ? 0L : model.getOrderId();
            if (modelMap.containsKey(orderId)) {
                modelMap.get(orderId).add(model);
            } else {
                List<ProductBookRecordModel> newModelList = new ArrayList<>();
                newModelList.add(model);
                modelMap.put(orderId, newModelList);
            }
        }
        return modelMap;
    }

    /**
     * 添加定时任务
     *
     * @param bookId
     * @param taskType
     * @param excuteTime
     * @param handler
     * @return
     */
    private Message addProductBook(Long bookId, TaskType taskType, Date excuteTime, String handler) {
        Map<String, Object> dataMap = new LinkedHashMap<>();
        dataMap.put("bookId", bookId);
        dataMap.put("taskType", taskType);
        return scheduleJobService.addJob(YgQuartzJob.ProductBook, taskType + "_" + bookId.toString(), excuteTime, dataMap, handler);
    }
}
